package cool.webstudy.singletondynamicscheduler.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import cool.webstudy.singletondynamicscheduler.constant.enums.DelFlagEnum;
import cool.webstudy.singletondynamicscheduler.constant.enums.EnabledStatusFlagEnum;
import cool.webstudy.singletondynamicscheduler.mapper.scheduler.SchedulerTaskRecordMapper;
import cool.webstudy.singletondynamicscheduler.model.dto.scheduler.CreateSchedulerTaskDTO;
import cool.webstudy.singletondynamicscheduler.model.dto.scheduler.UpdateSchedulerTaskDTO;
import cool.webstudy.singletondynamicscheduler.model.po.scheduler.SchedulerTaskRecordPO;
import cool.webstudy.singletondynamicscheduler.service.ISchedulerTaskService;
import cool.webstudy.singletondynamicscheduler.utils.UUIDUtil;
import cool.webstudy.singletondynamicscheduler.utils.scheduler.CronTaskRegistrar;
import cool.webstudy.singletondynamicscheduler.utils.scheduler.SchedulerRunnable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Objects;

/**
 * @author think
 * @date 2025/2/20 14:54
 * @description: 定时任务操作接口实现类
 */
@Service
public class SchedulerTaskServiceImpl implements ISchedulerTaskService {
    private static final Logger logger = LoggerFactory.getLogger(SchedulerTaskServiceImpl.class);
    @Autowired
    private CronTaskRegistrar cronTaskRegistrar;
    @Autowired
    private SchedulerTaskRecordMapper schedulerTaskRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createSchedulerTask(CreateSchedulerTaskDTO dto) {
        if (Objects.nonNull(dto)) {
            SchedulerTaskRecordPO schedulerTaskRecordPO = new SchedulerTaskRecordPO();
            schedulerTaskRecordPO.setBeanName(dto.getBeanName());
            schedulerTaskRecordPO.setMethodName(dto.getMethodName());
            schedulerTaskRecordPO.setMethodParams(dto.getMethodParams());
            schedulerTaskRecordPO.setCronExpression(dto.getCronExpression());
            schedulerTaskRecordPO.setTaskStatus(dto.getTaskStatus());
            schedulerTaskRecordPO.setRemark(dto.getRemark());
            schedulerTaskRecordPO.setUnCode(UUIDUtil.getUUID());
            schedulerTaskRecordPO.setCreateBy("system");
            schedulerTaskRecordPO.setCreateTime(new Date());
            schedulerTaskRecordPO.setUpdateBy("system");
            schedulerTaskRecordPO.setUpdateTime(new Date());
            schedulerTaskRecordPO.setDelFlag(DelFlagEnum.NOT_DEL_FLAG.getFlag());
            try {
                int result = schedulerTaskRecordMapper.insert(schedulerTaskRecordPO);
                //如果插入成功，并且任务状态为启用，则添加到定时任务调度器中执行
                if (result > 0 && EnabledStatusFlagEnum.ENABLED.getFlag().equals(dto.getTaskStatus().getFlag())) {
                    SchedulerRunnable task = new SchedulerRunnable(schedulerTaskRecordPO.getUnCode(), schedulerTaskRecordPO.getBeanName(), schedulerTaskRecordPO.getMethodName(), schedulerTaskRecordPO.getMethodParams());
                    cronTaskRegistrar.addCronTask(task, schedulerTaskRecordPO.getCronExpression());
                    logger.info("定时任务创建成功...");
                }
                return true;
            } catch (Exception e) {
                logger.error("创建定时任务失败：{}", e.getMessage());
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateSchedulerTask(UpdateSchedulerTaskDTO dto) {
        if (Objects.nonNull(dto)) {
            //先查询当前任务
            LambdaQueryWrapper<SchedulerTaskRecordPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SchedulerTaskRecordPO::getUnCode, dto.getUnCode());
            SchedulerTaskRecordPO schedulerTaskRecordPO = schedulerTaskRecordMapper.selectOne(queryWrapper);
            if (Objects.isNull(schedulerTaskRecordPO)) {
                logger.error("定时任务:{} 不存在...", dto.getUnCode());
                return false;
            }
            SchedulerRunnable currentTask = new SchedulerRunnable(schedulerTaskRecordPO.getUnCode(), schedulerTaskRecordPO.getBeanName(), schedulerTaskRecordPO.getMethodName(), schedulerTaskRecordPO.getMethodParams());
            //如果当前任务状态为启用，则从调度器中移除
            if (EnabledStatusFlagEnum.ENABLED.getFlag().equals(schedulerTaskRecordPO.getTaskStatus().getFlag())) {
                cronTaskRegistrar.removeCronTask(currentTask);
            }
            //更新任务记录
            LambdaUpdateWrapper<SchedulerTaskRecordPO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(SchedulerTaskRecordPO::getUnCode, dto.getUnCode())
                    .set(SchedulerTaskRecordPO::getBeanName, dto.getBeanName())
                    .set(SchedulerTaskRecordPO::getMethodName, dto.getMethodName())
                    .set(SchedulerTaskRecordPO::getMethodParams, dto.getMethodParams())
                    .set(SchedulerTaskRecordPO::getCronExpression, dto.getCronExpression())
                    .set(SchedulerTaskRecordPO::getTaskStatus, dto.getTaskStatus())
                    .set(SchedulerTaskRecordPO::getRemark, dto.getRemark())
                    .set(SchedulerTaskRecordPO::getUpdateBy, "system")
                    .set(SchedulerTaskRecordPO::getUpdateTime, new Date());
            try {
                int result = schedulerTaskRecordMapper.update(null, updateWrapper);
                //如果更新成功，并且任务状态为启用，则添加到定时任务调度器中执行
                if (result > 0 && EnabledStatusFlagEnum.ENABLED.getFlag().equals(dto.getTaskStatus().getFlag())) {
                    SchedulerRunnable newTask = new SchedulerRunnable(dto.getUnCode(), dto.getBeanName(), dto.getMethodName(), dto.getMethodParams());
                    cronTaskRegistrar.addCronTask(newTask, dto.getCronExpression());
                }
                return true;
            } catch (Exception e) {
                logger.error("更新定时任务失败：{}", e.getMessage());
                return false;
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteSchedulerTask(String unCode) {
        if (Objects.nonNull(unCode)) {
            //先查询当前任务
            LambdaQueryWrapper<SchedulerTaskRecordPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SchedulerTaskRecordPO::getUnCode, unCode);
            SchedulerTaskRecordPO schedulerTaskRecordPO = schedulerTaskRecordMapper.selectOne(queryWrapper);
            if (Objects.isNull(schedulerTaskRecordPO)) {
                logger.error("定时任务:{} 不存在...", unCode);
                return false;
            }
            //删除任务记录
            LambdaUpdateWrapper<SchedulerTaskRecordPO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(SchedulerTaskRecordPO::getUnCode, unCode)
                    .set(SchedulerTaskRecordPO::getDelFlag, DelFlagEnum.DEL_FLAG.getFlag())
                    .set(SchedulerTaskRecordPO::getUpdateBy, "system")
                    .set(SchedulerTaskRecordPO::getUpdateTime, new Date());
            try {
                int result = schedulerTaskRecordMapper.update(null, updateWrapper);
                if (result > 0) {
                    //如果当前任务状态为启用，则从调度器中移除
                    if (EnabledStatusFlagEnum.ENABLED.getFlag().equals(schedulerTaskRecordPO.getTaskStatus().getFlag())) {
                        SchedulerRunnable currentTask = new SchedulerRunnable(schedulerTaskRecordPO.getUnCode(), schedulerTaskRecordPO.getBeanName(), schedulerTaskRecordPO.getMethodName(), schedulerTaskRecordPO.getMethodParams());
                        cronTaskRegistrar.removeCronTask(currentTask);
                    }
                    logger.info("定时任务删除成功...");
                }
                return true;
            } catch (Exception e) {
                logger.error("删除定时任务失败：{}", e.getMessage());
                return false;
            }
        }
        return false;
    }
}
